home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / misc / 40 / shk1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-07-17  |  8.4 KB  |  329 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* shk.c - version 1.0.3 */
  3.  
  4. #include "hack.h"
  5. #ifdef QUEST
  6. int shlevel = 0;
  7. struct monst *shopkeeper = 0;
  8. struct obj *billobjs = 0;
  9. obfree(obj,merge) register struct obj *obj, *merge; {
  10.     free((char *) obj);
  11. }
  12. inshop(){ return(0); }
  13. addtobill(){}
  14. subfrombill(){}
  15. splitbill(){}
  16. dopay(){ return(0); }
  17. paybill(){}
  18. doinvbill(){ return(0); }
  19. shkdead(){}
  20. shkcatch(){ return(0); }
  21. shk_move(){ return(0); }
  22. replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
  23. char *shkname(){ return(""); }
  24.  
  25. #else QUEST
  26. #include    "mfndpos.h"
  27. #include    "mkroom.h"
  28. #include    "eshk.h"
  29.  
  30. #define    ESHK(mon)    ((struct eshk *)(&(mon->mextra[0])))
  31. #define    NOTANGRY(mon)    mon->mpeaceful
  32. #define    ANGRY(mon)    !NOTANGRY(mon)
  33.  
  34. extern char plname[], *xname();
  35. extern struct obj *o_on(), *bp_to_obj();
  36.  
  37. /* Descriptor of current shopkeeper. Note that the bill need not be
  38.    per-shopkeeper, since it is valid only when in a shop. */
  39. struct monst *shopkeeper = 0;
  40. struct bill_x *bill;
  41. int shlevel = 0;    /* level of this shopkeeper */
  42.        struct obj *billobjs;    /* objects on bill with bp->useup */
  43.                 /* only accessed here and by save & restore */
  44. long int total;        /* filled by addupbill() */
  45. long int followmsg;    /* last time of follow message */
  46.  
  47. /*
  48.     invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
  49.         obj->quan <= bp->bquan
  50.  */
  51.  
  52.  
  53. char shtypes[] = {    /* 8 shoptypes: 7 specialized, 1 mixed */
  54.     RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
  55.     POTION_SYM, ARMOR_SYM, 0
  56. };
  57.  
  58. char *shopnam[] = {
  59.     "engagement ring", "walking cane", "antique weapon",
  60.     "delicatessen", "second hand book", "liquor",
  61.     "used armor", "assorted antiques"
  62. };
  63.  
  64. char *
  65. shkname(mtmp)                /* called in do_name.c */
  66. register struct monst *mtmp;
  67. {
  68.     return(ESHK(mtmp)->shknam);
  69. }
  70.  
  71. shkdead(mtmp)                /* called in mon.c */
  72. register struct monst *mtmp;
  73. {
  74.     register struct eshk *eshk = ESHK(mtmp);
  75.  
  76.     if(eshk->shoplevel == dlevel)
  77.         rooms[eshk->shoproom].rtype = 0;
  78.     if(mtmp == shopkeeper) {
  79.         setpaid();
  80.         shopkeeper = 0;
  81.         bill = (struct bill_x *) -1000;    /* dump core when referenced */
  82.     }
  83. }
  84.  
  85. replshk(mtmp,mtmp2)
  86. register struct monst *mtmp, *mtmp2;
  87. {
  88.     if(mtmp == shopkeeper) {
  89.         shopkeeper = mtmp2;
  90.         bill = &(ESHK(shopkeeper)->bill[0]);
  91.     }
  92. }
  93.  
  94. setpaid(){    /* caller has checked that shopkeeper exists */
  95.         /* either we paid or left the shop or he just died */
  96. register struct obj *obj;
  97. register struct monst *mtmp;
  98.     for(obj = invent; obj; obj = obj->nobj)
  99.         obj->unpaid = 0;
  100.     for(obj = fobj; obj; obj = obj->nobj)
  101.         obj->unpaid = 0;
  102.     for(obj = fcobj; obj; obj = obj->nobj)
  103.         obj->unpaid = 0;
  104.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  105.         for(obj = mtmp->minvent; obj; obj = obj->nobj)
  106.             obj->unpaid = 0;
  107.     for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
  108.         for(obj = mtmp->minvent; obj; obj = obj->nobj)
  109.             obj->unpaid = 0;
  110.     while(obj = billobjs){
  111.         billobjs = obj->nobj;
  112.         free((char *) obj);
  113.     }
  114.     ESHK(shopkeeper)->billct = 0;
  115. }
  116.  
  117. addupbill(){    /* delivers result in total */
  118.         /* caller has checked that shopkeeper exists */
  119. register ct = ESHK(shopkeeper)->billct;
  120. register struct bill_x *bp = bill;
  121.     total = 0;
  122.     while(ct--){
  123.         total += bp->price * bp->bquan;
  124.         bp++;
  125.     }
  126. }
  127.  
  128. inshop(){
  129. register roomno = inroom(u.ux,u.uy);
  130.  
  131.     /* Did we just leave a shop? */
  132.     if(u.uinshop &&
  133.         (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
  134. #ifdef DGK
  135.     /* This is part of the bugfix for shopkeepers not having their
  136.      * bill paid.  As reported by ab@unido -dgk
  137.      */
  138.         if(shopkeeper) {
  139.             if(ESHK(shopkeeper)->billct) {
  140.             if (inroom(shopkeeper->mx, shopkeeper->my) ==
  141.                  u.uinshop - 1)
  142.                 pline("Somehow you escaped the shop without paying!");
  143.             addupbill();
  144.             pline("You stole for a total worth of %ld zorkmids.",
  145.                 total);
  146.             ESHK(shopkeeper)->robbed += total;
  147.             setpaid();
  148.             if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
  149.                 == (rn2(3) == 0))
  150.                 ESHK(shopkeeper)->following = 1;
  151.             }
  152.             shopkeeper = 0;
  153.             shlevel = 0;
  154.         }
  155.         u.uinshop = 0;
  156. #else
  157.         u.uinshop = 0;
  158.         if(shopkeeper) {
  159.             if(ESHK(shopkeeper)->billct) {
  160.             pline("Somehow you escaped the shop without paying!");
  161.             addupbill();
  162.             pline("You stole for a total worth of %ld zorkmids.",
  163.                 total);
  164.             ESHK(shopkeeper)->robbed += total;
  165.             setpaid();
  166.             if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
  167.                 == (rn2(3) == 0))
  168.                 ESHK(shopkeeper)->following = 1;
  169.             }
  170.             shopkeeper = 0;
  171.             shlevel = 0;
  172.         }
  173. #endif DGK
  174.     }
  175.  
  176.     /* Did we just enter a zoo of some kind? */
  177.     if(roomno >= 0) {
  178.         register int rt = rooms[roomno].rtype;
  179.         register struct monst *mtmp;
  180.         if(rt == ZOO) {
  181.             pline("Welcome to David's treasure zoo!");
  182.         } else
  183.         if(rt == SWAMP) {
  184.             pline("It looks rather muddy down here.");
  185.         } else
  186.         if(rt == MORGUE) {
  187.             if(midnight())
  188.                 pline("Go away! Go away!");
  189.             else
  190.                 pline("You get an uncanny feeling ...");
  191.         } else
  192.             rt = 0;
  193.         if(rt != 0) {
  194.             rooms[roomno].rtype = 0;
  195.             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  196.                 if(rt != ZOO || !rn2(3))
  197.                     mtmp->msleep = 0;
  198.         }
  199.     }
  200.  
  201.     /* Did we just enter a shop? */
  202.     if(roomno >= 0 && rooms[roomno].rtype >= 8) {
  203.         if(shlevel != dlevel || !shopkeeper
  204.                  || ESHK(shopkeeper)->shoproom != roomno)
  205.         findshk(roomno);
  206.         if(!shopkeeper) {
  207.         rooms[roomno].rtype = 0;
  208.         u.uinshop = 0;
  209. #ifndef DGK
  210.     /* This is part of the bugfix for shopkeepers not having their
  211.      * bill paid.  As reported by ab@unido -dgk
  212.      */
  213.         } else if(inroom(shopkeeper->mx, shopkeeper->my) != roomno) {
  214.         u.uinshop = 0;
  215. #endif DGK
  216.         } else if(!u.uinshop){
  217.         if(!ESHK(shopkeeper)->visitct ||
  218.             strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
  219.  
  220.             /* He seems to be new here */
  221.             ESHK(shopkeeper)->visitct = 0;
  222.             ESHK(shopkeeper)->following = 0;
  223.             (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
  224.             NOTANGRY(shopkeeper) = 1;
  225.         }
  226.         if(!ESHK(shopkeeper)->following) {
  227.             boolean box, pick;
  228.  
  229.             pline("Hello %s! Welcome%s to %s's %s shop!",
  230.             plname,
  231.             ESHK(shopkeeper)->visitct++ ? " again" : "",
  232.             shkname(shopkeeper),
  233.             shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );
  234.             box = carrying(ICE_BOX);
  235.             pick = carrying(PICK_AXE);
  236.             if(box || pick) {
  237.             if(dochug(shopkeeper)) {
  238.                 u.uinshop = 0;    /* he died moving */
  239.                 return(0);
  240.             }
  241.             pline("Will you please leave your %s outside?",
  242.                 (box && pick) ? "box and pick-axe" :
  243.                 box ? "box" : "pick-axe");
  244.             }
  245.         }
  246.         u.uinshop = roomno + 1;
  247.         }
  248.     }
  249.     return(u.uinshop);
  250. }
  251.  
  252. findshk(roomno)
  253. register roomno;
  254. {
  255. register struct monst *mtmp;
  256.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  257.         if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
  258.                && ESHK(mtmp)->shoplevel == dlevel) {
  259.         shopkeeper = mtmp;
  260.         bill = &(ESHK(shopkeeper)->bill[0]);
  261.         shlevel = dlevel;
  262.         if(ANGRY(shopkeeper) &&
  263.            strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
  264.             NOTANGRY(shopkeeper) = 1;
  265.         /* billobjs = 0; -- this is wrong if we save in a shop */
  266.         /* (and it is harmless to have too many things in billobjs) */
  267.         return;
  268.     }
  269.     shopkeeper = 0;
  270.     shlevel = 0;
  271.     bill = (struct bill_x *) -1000;    /* dump core when referenced */
  272. }
  273.  
  274. struct bill_x *
  275. onbill(obj) register struct obj *obj; {
  276. register struct bill_x *bp;
  277.     if(!shopkeeper) return(0);
  278.     for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
  279.         if(bp->bo_id == obj->o_id) {
  280.             if(!obj->unpaid) pline("onbill: paid obj on bill?");
  281.             return(bp);
  282.         }
  283.     if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
  284.     return(0);
  285. }
  286.  
  287. /* called with two args on merge */
  288. obfree(obj,merge) register struct obj *obj, *merge; {
  289. register struct bill_x *bp = onbill(obj);
  290. register struct bill_x *bpm;
  291.     if(bp) {
  292.         if(!merge){
  293.             bp->useup = 1;
  294.             obj->unpaid = 0;    /* only for doinvbill */
  295.             obj->nobj = billobjs;
  296.             billobjs = obj;
  297.             return;
  298.         }
  299.         bpm = onbill(merge);
  300.         if(!bpm){
  301.             /* this used to be a rename */
  302.             impossible("obfree: not on bill??");
  303.             return;
  304.         } else {
  305.             /* this was a merger */
  306.             bpm->bquan += bp->bquan;
  307.             ESHK(shopkeeper)->billct--;
  308.             *bp = bill[ESHK(shopkeeper)->billct];
  309.         }
  310.     }
  311.     free((char *) obj);
  312. }
  313.  
  314. pay(tmp,shkp)
  315. long tmp;
  316. register struct monst *shkp;
  317. {
  318.     long robbed = ESHK(shkp)->robbed;
  319.  
  320.     u.ugold -= tmp;
  321.     shkp->mgold += tmp;
  322.     flags.botl = 1;
  323.     if(robbed) {
  324.         robbed -= tmp;
  325.         if(robbed < 0) robbed = 0;
  326.         ESHK(shkp)->robbed = robbed;
  327.     }
  328. }
  329.